package org.anderground.modules.editor.tools.geocoding;

import geo.google.GeoAddressStandardizer;
import geo.google.GeoException;
import geo.google.datamodel.GeoAddress;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

import org.anderground.core.model.ModelData;
import org.anderground.core.model.Station;

/**
 * @author Ilya Shurigyn
 */
@SuppressWarnings("serial")
class Details extends JScrollPane {
	JPanel panel = new JPanel();
	List<Entry> log = new ArrayList<Entry>();
	private static final Dimension preferredSize = new Dimension(400, 100);
	public static final int REQUEST_FAILD = 0, REQUEST_SUCCESSFULL = 1,
			REQUEST_SKIPPED = 2;
	private static final String SUCCESSFULL_COLOR = "#0000aa",
			SKIPPED_COLOR = "#bb7700", FAILD_COLOR = "#aa0000";
	private Geowindow parent;
	private ModelData data;

	public Details(ModelData data, Geowindow parent) {
		super();
		this.data = data;
		this.setPreferredSize(preferredSize);
		this.parent = parent;
		setVisible(true);
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		this.setViewportView(panel);
	}

	public void log(Station station, GeoAddress[] avaliableAddresses) {

		final Entry label = new Entry(station, avaliableAddresses);
		log.add(label);
		label.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseClicked(MouseEvent arg0) {
				// Logger.i(Details.this.getParent().getParent().getParent().
				// getParent() + "");
				// Geowindow parent = (Geowindow)
				// Details.this.getParent().getParent().getParent().getParent();
				new RequestDialog(label, parent).setVisible(true);
			}

		});
		panel.add(label);
	}

	public Entry[] getEntries() {
		return log.toArray(new Entry[0]);
	}

	class Entry extends JLabel {
		private Station station;

		public Station getStation() {
			return station;
		}

		private int requestStatus;
		private String request;
		private GeoAddress address;

		public GeoAddress getAddress() {
			return address;
		}

		private GeoAddress[] avaliableAddresses;

		public String getRequest() {
			return request;
		}

		public void setRequest(String request) {
			this.request = request;
		}

		public Entry(Station station, GeoAddress[] avaliableAddresses) {
			this.station = station;
			this.avaliableAddresses = avaliableAddresses;
			if (avaliableAddresses == null || avaliableAddresses.length == 0) {
				this.requestStatus = REQUEST_FAILD;
			} else if (avaliableAddresses.length == 1) {
				this.requestStatus = REQUEST_SUCCESSFULL;
				this.address = avaliableAddresses[0];
			} else if (avaliableAddresses.length > 1) {
				this.requestStatus = REQUEST_SKIPPED;
			}

			this.request = Geowindow.getRequestForStation(data, station);
			setText(request, requestStatus);
		}

		private void setText(String request, int requestStatus) {
			String color = getRequestColor(requestStatus);
			String text = "<html><font color=" + color + ">" + request
					+ "</font></html>";
			this.setText(text);
		}

		private String getRequestColor(int requestStatus) {
			String color = "#000000";
			switch (requestStatus) {
			case REQUEST_SUCCESSFULL:
				color = SUCCESSFULL_COLOR;
				break;
			case REQUEST_SKIPPED:
				color = SKIPPED_COLOR;
				break;
			case REQUEST_FAILD:
				color = FAILD_COLOR;
				break;
			}
			return color;
		}

		public void setRequestStatus(int requestStatus) {
			this.requestStatus = requestStatus;
			setText(request, requestStatus);
			this.repaint();

		}

	}

	class RequestDialog extends JDialog {
		JTextField request = new JTextField();
		DefaultListModel listData = new DefaultListModel();
		JList list;
		Entry entry;
		private Geowindow parentWin;

		public RequestDialog(final Entry entry, Geowindow parent) {
			super(parent);
			this.parentWin = parent;
			setLayout(new GridLayout(3, 0));
			this.entry = entry;
			list = new JList(listData);
			initList();
			if (entry.address != null)
				list.setSelectedIndex(indexOfCurrentAdress());
			this.add(list);
			this.add(request);
			this.request.setText(entry.getRequest());
			JPanel buttonPanel = new JPanel();
			buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
			JButton retry = new JButton("Retry");
			retry.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					onRetry(entry);
				}
			});
			JButton ok = new JButton("ok");
			ok.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					onOk(entry);
				}
			});
			// button.setAlignmentX(RIGHT_ALIGNMENT);
			buttonPanel.add(retry);
			buttonPanel.add(ok);
			add(buttonPanel);

			pack();
		}

		private int indexOfCurrentAdress() {

			for (int i = 0; i < entry.avaliableAddresses.length; i++) {
				if (entry.avaliableAddresses[i] == entry.address)
					return i;
			}
			return -1;
		}

		private void onOk(Entry entry) {
			if (list.isSelectionEmpty()) {
				return;
			}
			entry.address = entry.avaliableAddresses[list.getSelectedIndex()];
			entry.setRequest(request.getText());

			switch (entry.requestStatus) {
			case REQUEST_SKIPPED:
				parentWin.getStatPanel().incSuccessfull();
				parentWin.getStatPanel().decSkipped();
				break;
			case REQUEST_FAILD:
				parentWin.getStatPanel().incSuccessfull();
				parentWin.getStatPanel().decFailed();
				break;
			}
			entry.setRequestStatus(REQUEST_SUCCESSFULL);
			this.setVisible(false);

		}

		private void initList() {
			listData.clear();
			if (entry.avaliableAddresses != null) {
				String[] labels = new String[entry.avaliableAddresses.length];
				for (int i = 0; i < entry.avaliableAddresses.length; i++) {
					labels[i] = entry.avaliableAddresses[i].getAddressLine();
					listData.add(i, labels[i]);
				}

			}
		}

		private void onRetry(final Entry entry) {
			GeoAddressStandardizer standardizer = new GeoAddressStandardizer(
					GoogleAPIDeveloperData.API_KEY, 1000);
			try {
				entry.avaliableAddresses = standardizer
						.standardizeToGeoAddresses(request.getText()).toArray(
								new GeoAddress[1]);
				// RequestDialog.this.remove(list);
				initList();
				// RequestDialog.this.add(list);
				// RequestDialog.this.repaint();

			} catch (GeoException e1) {
				entry.avaliableAddresses = null;
				// e1.printStackTrace();
			}
		}
	}
}
